package cn.cycleif.app.service;

import cn.cycleif.app.domain.vo.NotificationVO;
import cn.cycleif.app.mapper.AnswerMapper;
import cn.cycleif.app.mapper.NotificationMapper;
import cn.cycleif.app.mapper.QuestionMapper;
import cn.cycleif.entity.Answer;
import cn.cycleif.entity.Notification;
import cn.cycleif.entity.Question;
import cn.cycleif.enums.InboxTypeEnum;
import cn.cycleif.util.PageUtil;
import cn.cycleif.util.R;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Date: 25/2/17-14:15
 * @Desc:
 */
@Service
@RequiredArgsConstructor
public class NotificationService extends ServiceImpl<NotificationMapper, Notification> {

  private final NotificationMapper notificationMapper;
  private final UserService        userService;

  private final QuestionMapper questionMapper;
  private final AnswerMapper   answerMapper;

  public R<Object> getPage(String type) {
    Page<Notification> page = new Page<>(PageUtil.getPageNo(), PageUtil.getPageSize());

    LambdaQueryWrapper<Notification> wrapper = getWrapperByType(type);

    Page<Notification> page1 = notificationMapper.selectPage(page, wrapper);
    // 添加信息
    Page<NotificationVO> voPage = new Page<>();
    voPage.setCurrent(page1.getCurrent());
    voPage.setSize(page1.getSize());
    voPage.setTotal(page1.getTotal());
    voPage.setPages(page1.getPages());

    List<Notification>   answers = page1.getRecords();
    List<NotificationVO> list    = answers.stream().map(this::appendExtraInfo).toList();
    voPage.setRecords(list);
    return R.success(voPage);
  }

  private NotificationVO appendExtraInfo(Notification notification) {
    NotificationVO vo = new NotificationVO();
    BeanUtils.copyProperties(notification, vo);
    if (notification.getRelateUserId() != null) {
      HashMap<String, Object> userInfo = userService.getUserSimpleInfo(notification.getRelateUserId(), null);
      vo.setRelateInfo(userInfo);
    }
    Map<String, Object> objInfo = new HashMap<>();
    switch (notification.getObjectType()) {
      case QUESTION -> {
        Question question = questionMapper.selectById(notification.getObjectId());
        objInfo.put("id", question.getId());
        objInfo.put("content", question.getTitle());
        objInfo.put("questionId", question.getId());
        objInfo.put("questionTitle", question.getTitle());
      }
      case ANSWER -> {
        Answer answer = answerMapper.selectById(notification.getObjectId());
        objInfo.put("id", answer.getId());
        objInfo.put("content", answer.getContent());
        Question question = questionMapper.selectById(answer.getQuestionId());
        objInfo.put("questionId", question.getId());
        objInfo.put("questionTitle", question.getTitle());
      }
      default -> {
      }
    }
    vo.setObjectInfo(objInfo);
    return vo;
  }

  public void addNotification(Notification notification) {
    notificationMapper.insert(notification);
  }

  public R<String> markRead(String type) {
    LambdaQueryWrapper<Notification> wrapper = getWrapperByType(type);

    List<Notification> notifications = notificationMapper.selectList(wrapper);

    for (Notification notification : notifications) {
      notification.setIsRead(1);
      notificationMapper.updateById(notification);
    }
    return R.success();
  }

  private LambdaQueryWrapper<Notification> getWrapperByType(String type) {
    int userId = StpUtil.getLoginIdAsInt();

    LambdaQueryWrapper<Notification> wrapper = new LambdaQueryWrapper<>();
    wrapper.eq(Notification::getUserId, userId);
    wrapper.orderByDesc(Notification::getCreateAt);
    switch (type) {
      case "posts" -> wrapper.eq(Notification::getType, InboxTypeEnum.POSTS);
      case "votes" -> wrapper.eq(Notification::getType, InboxTypeEnum.VOTES);
      case "other" -> wrapper.eq(Notification::getType, InboxTypeEnum.OTHER);
      default -> {
      }
    }
    return wrapper;
  }

  public R<String> getCount() {
    int                              userId  = StpUtil.getLoginIdAsInt();
    LambdaQueryWrapper<Notification> wrapper = new LambdaQueryWrapper<>();
    wrapper.eq(Notification::getUserId, userId);
    wrapper.eq(Notification::getIsRead, 0);
    Long count = notificationMapper.selectCount(wrapper);
    return R.success(String.valueOf(count));
  }

}
